import { 
  Component, 
  OnInit, 
  Input, 
  Output, 
  EventEmitter, 
  ComponentFactoryResolver, 
  ViewContainerRef, 
  ViewChild, 
  ElementRef, 
  Injector,
  Renderer2
} from '@angular/core';

import { SideComponentParams } from './side-component-params';

@Component({
  selector: 'ege-side-component-container',
  templateUrl: './side-component-container.component.html',
  styleUrls: ['./side-component-container.component.scss']
})
export class SideComponentContainerComponent implements OnInit {

  @Input() component: any;
  @Input() params: object;
  @Input() position: 'top'|'left'|'bottom'|'right';

  @Output() onChange: EventEmitter<any> = new EventEmitter();
  @Output() onClose: EventEmitter<any> = new EventEmitter();
  @Output() onError: EventEmitter<any> = new EventEmitter();

  @ViewChild('container', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;
  @ViewChild('sideComponent') sideComponent: ElementRef;

  showStyle: object;
  removeStyle: object;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private renderer: Renderer2
  ) { }

  ngOnInit() {
    this.viewContainerRef.clear();
    this.componentLoader();
  }

  componentLoader(): void {
    const params: SideComponentParams = new SideComponentParams(this.params);
    const injector: Injector = Injector.create({
      providers: [
        { provide: SideComponentParams, useValue: params }
      ]
    });
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
    const componentRef = this.viewContainerRef.createComponent(componentFactory, null, injector);
    params._onChange$.subscribe((data: any) => this.onChange.emit(data));
    params._onClose$.subscribe(() => {
      this.remove();
      setTimeout(() => {
        this.onClose.emit();
        this.viewContainerRef.clear();
      }, 300);
    });
    params._onError$.subscribe((error: any) => {
      this.remove();
      setTimeout(() => {
        this.onError.emit(error);
        this.viewContainerRef.clear();
      }, 300);
    });
    this.initialPosition();
    setTimeout(() => this.show(), 0);
  }

  initialPosition(): void {
    const nativeElement = this.sideComponent.nativeElement;
    const offsetWidth = nativeElement.offsetWidth;
    const offsetHeight = nativeElement.offsetHeight;
    let value: number|string = 0;
    if(this.position === 'top' || this.position === 'bottom') {
      value = `${(offsetHeight + 20) * -1}px`
    } else {
      value = `${(offsetWidth + 20) * -1}px`
    }
    this.renderer.setStyle(nativeElement, 'opacity', 0);
    this.setStyles(nativeElement, this.position, value, 'initial');
  }

  show(): void {
    const nativeElement = this.sideComponent.nativeElement;
    this.setStyles(nativeElement, this.position, 0, 'in');
    this.renderer.setStyle(nativeElement, 'opacity', 1);
  }

  remove(): void {
    const nativeElement = this.sideComponent.nativeElement;
    const offsetWidth = nativeElement.offsetWidth;
    const offsetHeight = nativeElement.offsetHeight;
    let value:string|number = 0;
    if(this.position === 'top' || this.position === 'bottom') {
      value = `${(offsetHeight + 20) * -1}px`
    } else {
      value = `${(offsetWidth + 20) * -1}px`
    }
    this.setStyles(nativeElement, this.position, value, 'out');
  }

  setStyles(nativeElement: any, position: 'top'|'left'|'bottom'|'right', value: number|string, status: 'in'|'out'|'initial'): void {
    this.renderer.setStyle(nativeElement, position, value);
    if(status !== 'initial') {
      this.renderer.setStyle(nativeElement, `transition`, `${position} .3s cubic-bezier(.645,.045,.355,1)`);
    }
  }


  

}
